﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Minesweeper
{
    public class Minesweeper
    {

        static void Main(string[] args)
        {
            const int maxScore = 35;

            string command = string.Empty;
            char[,] gameField = GenerateField();
            char[,] minesField = GenerateMines();
            int currentScore = 0;

            List<HighScore> highScoreList = new List<HighScore>(6);
            int row = 0;
            int col = 0;

            bool isNewGame = true;
            bool isMineHitted = false;
            bool isGameOver = false;

            do
            {
                if (isNewGame)
                {
                    Console.WriteLine("Hajde da igraem na “Mini4KI”. Probvaj si kasmeta da otkriesh poleteta bez mini4ki." +
                    " Komanda 'top' pokazva klasiraneto, 'restart' po4va nova igra, 'exit' izliza i hajde 4ao!");
                    DrawMineBoard(gameField);
                    isNewGame = false;
                }

                Console.Write("Daj red i kolona : ");
                command = Console.ReadLine().Trim();
                if (command.Length >= 3)
                {
                    if (int.TryParse(command[0].ToString(), out row) &&
                        int.TryParse(command[2].ToString(), out col) &&
                        row <= gameField.GetLength(0) && col <= gameField.GetLength(1))
                    {
                        command = "turn";
                    }
                }

                switch (command)
                {
                    case "top":
                        {
                            HighScores(highScoreList);
                        }
                        break;
                    case "restart":
                        {
                            gameField = GenerateField();
                            minesField = GenerateMines();
                            DrawMineBoard(gameField);
                            isMineHitted = false;
                            isNewGame = false;
                        }
                        break;
                    case "exit":
                        {
                            Console.WriteLine("4a0, 4a0, 4a0!");
                        }
                        break;
                    case "turn":
                        {
                            if (minesField[row, col] != '*')
                            {
                                if (minesField[row, col] == '-')
                                {
                                    CreateSurroundMinesField(gameField, minesField, row, col);
                                    currentScore++;
                                }
                                if (maxScore == currentScore)
                                {
                                    isGameOver = true;
                                }
                                else
                                {
                                    DrawMineBoard(gameField);
                                }
                            }
                            else
                            {
                                isMineHitted = true;
                            }
                        }
                        break;
                    default:
                        {
                            Console.WriteLine("\nGreshka! nevalidna Komanda\n");
                        }
                        break;
                }

                if (isMineHitted)
                {
                    DrawMineBoard(minesField);
                    Console.Write("\nHrrrrrr! Umria gerojski s {0} to4ki. " +
                        "Daj si niknejm: ", currentScore);
                    string playerName = Console.ReadLine();
                    HighScore playerResult = new HighScore(playerName, currentScore);

                    if (highScoreList.Count < 5)
                    {
                        highScoreList.Add(playerResult);
                    }

                    else
                    {
                        for (int i = 0; i < highScoreList.Count; i++)
                        {
                            if (highScoreList[i].PlayerScore < playerResult.PlayerScore)
                            {
                                highScoreList.Insert(i, playerResult);
                                highScoreList.RemoveAt(highScoreList.Count - 1);
                                break;
                            }
                        }
                    }

                    highScoreList.Sort((HighScore r1, HighScore r2) => r2.PlayerName.CompareTo(r1.PlayerName));
                    highScoreList.Sort((HighScore r1, HighScore r2) => r2.PlayerScore.CompareTo(r1.PlayerScore));
                    HighScores(highScoreList);

                    gameField = GenerateField();
                    minesField = GenerateMines();
                    currentScore = 0;
                    isMineHitted = false;
                    isNewGame = true;
                }

                if (isGameOver)
                {
                    Console.WriteLine("\nBRAVOOOS! Otvri 35 kletki bez kapka kryv.");
                    DrawMineBoard(minesField);
                    Console.WriteLine("Daj si imeto, batka: ");
                    string imeee = Console.ReadLine();
                    HighScore to4kii = new HighScore(imeee, currentScore);
                    highScoreList.Add(to4kii);
                    HighScores(highScoreList);
                    gameField = GenerateField();
                    minesField = GenerateMines();
                    currentScore = 0;
                    isGameOver = false;
                    isNewGame = true;
                }
            }

            while (command != "exit");
            Console.WriteLine("Made in Bulgaria - Uauahahahahaha!");
            Console.WriteLine("AREEEEEEeeeeeee.");
            Console.Read();
        }

        private static void HighScores(List<HighScore> score)
        {
            Console.WriteLine("\nTo4KI:");
            if (score.Count > 0)
            {
                for (int i = 0; i < score.Count; i++)
                {
                    Console.WriteLine("{0}. {1} --> {2} kutii",
                        i + 1, score[i].PlayerName, score[i].PlayerScore);
                }

                Console.WriteLine();
            }
            else
            {
                Console.WriteLine("prazna klasaciq!\n");
            }
        }

        private static void CreateSurroundMinesField(char[,] field, char[,] mines, int currentRow, int currentCol)
        {
            char minesCount = SurroundMinesCount(mines, currentRow, currentCol);
            mines[currentRow, currentCol] = minesCount;
            field[currentRow, currentCol] = minesCount;
        }

        private static void DrawMineBoard(char[,] board)
        {
            int boardRow = board.GetLength(0);
            int boardCol = board.GetLength(1);
            Console.WriteLine("\n    0 1 2 3 4 5 6 7 8 9");
            Console.WriteLine("   ---------------------");

            for (int i = 0; i < boardRow; i++)
            {
                Console.Write("{0} | ", i);

                for (int j = 0; j < boardCol; j++)
                {
                    Console.Write(string.Format("{0} ", board[i, j]));
                }

                Console.Write("|");
                Console.WriteLine();
            }

            Console.WriteLine("   ---------------------\n");
        }

        private static char[,] GenerateField()
        {
            int fieldRows = 5;
            int fieldColumns = 10;
            char[,] board = new char[fieldRows, fieldColumns];
            for (int i = 0; i < fieldRows; i++)
            {
                for (int j = 0; j < fieldColumns; j++)
                {
                    board[i, j] = '?';
                }
            }

            return board;
        }

        private static char[,] GenerateMines()
        {
            int fieldRows = 5;
            int fieldColumns = 10;
            char[,] gameField = new char[fieldRows, fieldColumns];

            for (int i = 0; i < fieldRows; i++)
            {
                for (int j = 0; j < fieldColumns; j++)
                {
                    gameField[i, j] = '-';
                }
            }

            List<int> allMinesPositions = new List<int>();
            while (allMinesPositions.Count < 15)
            {
                Random random = new Random();
                int minePosition = random.Next(50);
                if (!allMinesPositions.Contains(minePosition))
                {
                    allMinesPositions.Add(minePosition);
                }
            }

            foreach (int minePosition in allMinesPositions)
            {
                int currentCol = (minePosition / fieldColumns);
                int currentRow = (minePosition % fieldColumns);
                if (currentRow == 0 && minePosition != 0)
                {
                    currentCol--;
                    currentRow = fieldColumns;
                }
                else
                {
                    currentRow++;
                }
                gameField[currentCol, currentRow - 1] = '*';
            }

            return gameField;
        }

        private static char SurroundMinesCount(char[,] field, int currentRow, int currentCol)
        {
            int numberOfMines = 0;
            int fieldRows = field.GetLength(0);
            int fieldCols = field.GetLength(1);

            if (currentRow - 1 >= 0)
            {
                if (field[currentRow - 1, currentCol] == '*')
                {
                    numberOfMines++;
                }
            }

            if (currentRow + 1 < fieldRows)
            {
                if (field[currentRow + 1, currentCol] == '*')
                {
                    numberOfMines++;
                }
            }

            if (currentCol - 1 >= 0)
            {
                if (field[currentRow, currentCol - 1] == '*')
                {
                    numberOfMines++;
                }
            }

            if (currentCol + 1 < fieldCols)
            {
                if (field[currentRow, currentCol + 1] == '*')
                {
                    numberOfMines++;
                }
            }

            if ((currentRow - 1 >= 0) && (currentCol - 1 >= 0))
            {
                if (field[currentRow - 1, currentCol - 1] == '*')
                {
                    numberOfMines++;
                }
            }

            if ((currentRow - 1 >= 0) && (currentCol + 1 < fieldCols))
            {
                if (field[currentRow - 1, currentCol + 1] == '*')
                {
                    numberOfMines++;
                }
            }

            if ((currentRow + 1 < fieldRows) && (currentCol - 1 >= 0))
            {
                if (field[currentRow + 1, currentCol - 1] == '*')
                {
                    numberOfMines++;
                }
            }

            if ((currentRow + 1 < fieldRows) && (currentCol + 1 < fieldCols))
            {
                if (field[currentRow + 1, currentCol + 1] == '*')
                {
                    numberOfMines++;
                }
            }

            return char.Parse(numberOfMines.ToString());
        }
    }
}
